home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / byte1087.arc / MALLETT.ARC / CPLUS.SRC next >
Encoding:
Text File  |  1980-01-29  |  8.6 KB  |  336 lines

  1.  
  2.  
  3. /* score_c.h - Definitions for classes related to the "score" program
  4.                 written for the Byte C++ Review
  5.                 
  6.         May 1987 Mark E. Mallett
  7.         
  8. */
  9.  
  10. #ifndef NULL
  11. #define NULL    (char *)0
  12. #endif
  13.  
  14. /* This header file declares the following classes: */
  15. class   SCORE_ITEM;
  16. class   REST;                           // Derived from SCORE_ITEM
  17. class   NOTE;                           // Derived from SCORE_ITEM
  18. class   CHORD;                          // Derived from SCORE_ITEM
  19.  
  20. class   SEQUENCE;                       // Relates to SCORE_ITEM
  21. class   SEQ_ITER;                       // Allows following a SEQUENCE
  22.  
  23. enum NOTEVAL { C, Csh, D, Dsh, E, F, Fsh, G, Gsh, A, Ash, B };
  24. istream& operator>> ( istream&, NOTEVAL& );
  25.     
  26. class SCORE_ITEM                        // Base class for all score items
  27.     {
  28.     int         duration;               // How long this item persists
  29.     SCORE_ITEM* next;                   // Next SCORE_ITEM in the sequence
  30.     friend class SEQUENCE;
  31.     friend class SEQ_ITER;
  32.     friend istream& operator>> ( istream&, SCORE_ITEM& );
  33. public:
  34.     SCORE_ITEM( int d = 3 ){ duration = d; }
  35.     ~SCORE_ITEM(){}
  36.  
  37.     int dur() { return duration; }       // Retrieves duration value
  38.     virtual void play();                // Plays a score item
  39.     };
  40.  
  41.  
  42. class REST : public SCORE_ITEM          // Musical rest-- marks a place
  43.     {
  44. public:
  45.     REST( int d = 3 ) : ( d ) {}
  46.     
  47.     void play();
  48.     };
  49.         
  50.  
  51. class NOTE : public SCORE_ITEM
  52.     {
  53.     NOTEVAL     noteval;                // Value of the note
  54.     friend istream& operator>> ( istream&, NOTE& );
  55. public:
  56.     NOTE( NOTEVAL n = C, int d = 3 ) : ( d ) { noteval = n; }
  57.     ~NOTE(){};
  58.  
  59.     void play();
  60.     };
  61.  
  62. class CHORD: public SCORE_ITEM
  63.     {
  64.     int         notemask;               // Notes that make up this chord
  65.     friend istream& operator>> ( istream&, CHORD& );
  66. public:
  67.     CHORD( int n = 0 , int d = 3 ) : ( d ) { notemask = n; }
  68.     ~CHORD(){}
  69.     
  70.     void play();
  71.     };
  72.  
  73.  
  74. class SEQUENCE                          // Class allowing sequence operations.
  75.     {
  76.     SCORE_ITEM* item;                   // Points to item
  77.     SCORE_ITEM*  last;                   // Points to last item
  78.     SEQUENCE&   append( SCORE_ITEM *si )
  79.          { if ( item == (SCORE_ITEM *)NULL )  item = last = si;
  80.            last->next = si; last = si; si->next = (SCORE_ITEM *)NULL;
  81.            return *this; }
  82.     friend class SEQ_ITER;
  83. public:
  84.     SEQUENCE(){ item = last = (SCORE_ITEM *)NULL; };
  85.     SEQUENCE( SCORE_ITEM& si ) { item = last = &si; }
  86.     ~SEQUENCE(){}
  87.     SEQUENCE& operator= ( SCORE_ITEM& si ) { item = last = &si; return *this; }
  88.     SEQUENCE& operator= ( SEQUENCE& s2 )
  89.         { item = s2.item; last = s2.last; return *this; }
  90.     SEQUENCE& operator+ ( SCORE_ITEM& si ) { return append( &si ); }
  91.     SEQUENCE& operator+= ( SCORE_ITEM& si ) { return append( &si ); }
  92.     SEQUENCE& operator+= ( SCORE_ITEM* si ) { return append( si ); }
  93.     };
  94.  
  95.  
  96.  
  97. class SEQ_ITER                           // To follow a sequence with
  98.     {
  99.     SEQUENCE*   seq;                    // Ptr to song header
  100.     SCORE_ITEM* si;                     // Ptr to current item
  101. public:
  102.     SEQ_ITER( SEQUENCE& sq ){ seq = &sq; si = sq.item; }
  103.     ~SEQ_ITER(){}
  104.     SCORE_ITEM* operator()();           // Retrieve next one
  105.     };
  106.  
  107.  
  108.  
  109. ----------------------------------------------------------------------
  110.  
  111. /* score_c.c++ - Support functions for classes related to the "score" program
  112.                 written for the Byte C++ Review
  113.                 
  114.         May 1987 Mark E. Mallett
  115.         
  116. */
  117. #include <stream.h>
  118. #include <string.h>
  119. #include "score_c.h"
  120.  
  121.  
  122. /* Table of correlations between note names and noteval mnemonics */
  123. static struct { NOTEVAL nval; char* nname; } Nvtbl[13] = {
  124.         { C,    "C" },
  125.         { Csh,  "Csh" },
  126.         { D,    "D" },
  127.         { Dsh,  "Dsh" },
  128.         { E,    "E" },
  129.         { F,    "F" },
  130.         { Fsh,  "Fsh" },
  131.         { G,    "G" },
  132.         { Gsh,  "Gsh" },
  133.         { A,    "A" },
  134.         { Ash,  "Ash" },
  135.         { B,    "B" },
  136.  { 0,    "BAD" }         };
  137.  
  138.  
  139. void SCORE_ITEM :: play()               // play for generic score_items
  140. {
  141. cout << "generic item: duration=" << dec(duration,3) << "\n";
  142. }
  143.  
  144.  
  145. void REST :: play()
  146. {
  147. cout << "rest:         duration=" << dec(dur(),3) << "\n";
  148. }
  149.  
  150.  
  151. void NOTE :: play()
  152. {
  153.         int     i;
  154.  
  155. for( i = 0; i < 12; ++i )
  156.     if ( noteval == Nvtbl[i].nval )
  157.         break;
  158. cout << "note:         duration=" << dec(dur(),3)
  159.      << "  value: " << Nvtbl[i].nname << "\n";
  160. }
  161.  
  162.  
  163. void CHORD :: play()
  164. {
  165.         int     i;
  166.         int     nval;
  167.  
  168. cout << "chord:        duration=" << dec(dur(),3) << "  value:";
  169. for( nval = 0; nval < 12; ++nval )
  170.     if ( notemask & (1 << nval ) )
  171.         {
  172.         for( i = 0; i < 12; ++i )
  173.             if ( nval == Nvtbl[i].nval )
  174.                 break;
  175.         cout << " " << Nvtbl[i].nname;
  176.  }
  177.  
  178. cout << "\n";
  179. }
  180.  
  181.  
  182.  
  183. SCORE_ITEM* SEQ_ITER :: operator()()
  184. {
  185. SCORE_ITEM*     tsi = si;               // Copy of current ptr
  186. if ( si != (SCORE_ITEM *)NULL ) si = si -> next;
  187. return tsi;
  188. }
  189.  
  190.  
  191. istream& operator>> ( istream& s, NOTEVAL& n )
  192. {
  193.         int     i;
  194.         char    namebuf[100];
  195.  
  196. s >> (char *)&namebuf[0];                // Input name
  197. for( i = 0; i < 12; ++i )
  198.     if ( stricmp( namebuf, Nvtbl[i].nname ) == 0 )
  199.         break;
  200. if ( i < 12 )
  201.     n = Nvtbl[i].nval;
  202. else
  203.     cout << "Error: '" << namebuf << "' is not a note name\n";
  204. return s;
  205. }
  206.  
  207.         
  208. istream& operator>> ( istream& s, SCORE_ITEM& si )
  209. {
  210. s >> si.duration;
  211. return s;
  212. }
  213.  
  214.  
  215. istream& operator>> ( istream& s, NOTE& n )
  216. {
  217. s >> (SCORE_ITEM& ) n;
  218. s >> n.noteval;
  219. return s;
  220. }
  221.  
  222.  
  223. istream& operator>> ( istream& s, CHORD& c )
  224. {
  225.         NOTEVAL nval;
  226.         char    ch;
  227.  
  228. s >> (SCORE_ITEM& ) c;
  229. c.notemask = 0;                         // No notes
  230. for( ; ; )                              // Input notenames until no comma
  231.  
  232.     {
  233.     s >> (NOTEVAL &) nval;              // Get next note
  234.     c.notemask |= (1 << nval);
  235.     s >> ch;                            // Look for semi
  236.     if ( ch == ';' )                    // Quit when found
  237.  break;
  238.     s.putback( ch );                    // Re-use the not-semi
  239.     }
  240. return s;
  241. }
  242.  
  243.  
  244. ----------------------------------------------------------------------
  245.  
  246. /* score.c++ - Test program for the "score" classes,
  247.                 written for the Byte C++ Review
  248.                 
  249.         May 1987 Mark E. Mallett
  250.         
  251. */
  252.  
  253. #include <stream.h>
  254. #include <ctype.h>
  255.  
  256. #include "score_c.h"
  257. void    play( SEQUENCE& );
  258.  
  259.  
  260. main()
  261. {
  262.         SEQUENCE song1;
  263.         NOTE    c1(5), c2(10);
  264.  
  265. c1 = C;
  266. c2 = G;
  267. song1 = c1;
  268. song1 = song1 + c2 + NOTE(Dsh, 7);
  269. song1 += NOTE(Ash);
  270. play( song1 );
  271. cout << "\n\n";
  272.  
  273.  
  274.         SEQUENCE song2;
  275.         char    c;
  276. cout << "Enter each element of the song in the following formats\n\n";
  277. cout << "r dd                    to enter a rest\n";
  278. cout << "n dd note-name          to enter a note\n";
  279. cout << "c dd note-name... ;     to enter a chord\n"; 
  280. cout << "p                       to play the song\n";
  281. cout << "x                       to finish\n";
  282.  
  283. for( ; ; )                              // Loop until done 
  284.     {
  285.     cout << "\n> ";                     // Issue prompt
  286.     cin >> c;                           // Get key character
  287.     if ( isupper( c ) )
  288.         c = tolower( c );
  289.     if ( c == 'x' )
  290.         break;
  291.  
  292.     switch ( c )                        // Process input
  293.         {
  294.         case 'r':                       // rest
  295.      REST* rest = new REST;
  296.             cin >> *rest;
  297.             song2 += rest;
  298.             cout << "rest entered\n";
  299.             break;
  300.  
  301.         case 'n':                       // note
  302.             NOTE* note = new NOTE;
  303.             cin >> *note;
  304.             song2 += note;
  305.             cout << "note entered\n";
  306.             break;
  307.  
  308.         case 'c':                       // chord
  309.             CHORD* chord = new CHORD;
  310.             cin >> *chord;
  311.             song2 += chord;
  312.             cout << "chord entered\n";
  313.             break;
  314.  
  315.         case 'p':                       // Play
  316.             play( song2 );              // Play it
  317.             break;
  318.  
  319.         default:                        // Invalid
  320.             cout << "'" << chr(c) << "' isn't valid.\n";
  321.             break;
  322.         }
  323.     }
  324. }
  325.  
  326.  
  327. void play( SEQUENCE &song )             // Routine to play a song
  328. {
  329. SEQ_ITER next_seq(song);                // Get an iterator for the song
  330. SCORE_ITEM *siptr;
  331. while ( ( siptr = next_seq() ) != (SCORE_ITEM *)NULL )
  332.     siptr->play();
  333. }
  334.  
  335.             *** end Score ***
  336.